<?php
/** 
 * @desc 控制器基类
 * @author dengjing
 * @date 2020年11月9日 下午14:00:00
 */
namespace Common;

use Common\Models\User;
use Phalcon\Mvc\Controller;
use Phalcon\Exception;
use Phalcon\Request;

/**
 * 控制器基础类
 */
class BaseController extends Controller
{
    //请求参数
    protected $params;

    //header的信息
    protected $header;

    // 初始化
    public function initialize()
    {
        /*防止跨域*/
//        header('Access-Control-Allow-Origin: https://www.baidu.com'); //设置http://www.baidu.com允许跨域访问
//        header('Access-Control-Allow-Headers: X-Requested-With,X_Requested_With'); //设置允许的跨域header
        header("Content-Type: text/html; charset=utf-8");
        header('Access-Control-Allow-Origin:*');
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Allow-Methods: *');
        header("Access-Control-Allow-Headers: *");

        $this->header = $this->request->getHeaders();

        $postData = $this->request->getPost();
        $getData = $this->request->Get();
        if($postData && $getData){
            $this->params = array_merge($postData,$getData);
        }else{
            if($postData){
                $this->params = $postData;
            }else{
                $this->params = $getData;
            }
        }
        $source= "";
        if(isset($this->header['Source']) && !empty($this->header['Source'])){
            $source = $this->header['Source'];
        }else{
            if(isset($this->params['source']) && !empty($this->params['source'])){
                $source = $this->params['source'];

            }
        }
        $this->params['source'] = $source;

        $version = "";
        if(isset($this->header['Version']) && !empty($this->header['Version'])){
            $version = $this->header['Version'];
        }else{
            if(isset($this->params['version']) && !empty($this->params['version'])){
                $version = $this->params['version'];

            }
        }
        $this->params["version"] = $version;

        $timestamp = "";
        if(isset($this->header['Timestamp']) && !empty($this->header['Timestamp'])){
            $timestamp = $this->header['Timestamp'];
        }else{
            if(isset($this->params['timestamp']) && !empty($this->params['timestamp'])){
                $timestamp = $this->params['timestamp'];

            }
        }
        $this->params['timestamp'] = $timestamp;

        $token = "";
        if(isset($this->header['Token']) && !empty($this->header['Token'])){
            $token = $this->header['Token'];
        }else{
            if(isset($this->params['token']) && !empty($this->params['token'])){
                $token = $this->params['token'];

            }
        }
        $this->params['token'] = $token;


        if(isset($this->params['imei']) && !empty($this->params['imei'])){
            $this->params['imei_full'] = $this->params['imei'];
            if(strpos($this->params['imei'],',') !== false) {
                $imei_arr = explode(',', $this->params['imei']);
                if (count($imei_arr) == 2) {
                    $this->params['imei'] = $imei_arr[0];
                }
            }
        }

    }

    
    /**
     * 过滤参数
     * @param array $data 数据源
     * @param string $name 参数名
     * @param string|array $filter 过滤类型，支持string、trim、absint、int、email、float、int!、float!、alphanum、striptags、lower、upper、url、special_chars
     * 当为false时，不使用默认过滤，当为字符串例如'string,trim'时采用参数过滤 ，当为数组例如['string','trim']时采用参数+默认过滤，当为null等其他值时时采用默认过滤
     * @param mixed $defaultValue 默认值
     * @param bool $noRecursive 不递归过滤
     * @return mixed
     * @author zhaoyang
     * @date 2018年5月9日 下午8:20:15
     */
    final protected function sanitize(array $data, $name = null, $filter = null, $defaultValue = null, $noRecursive = false){
        $nowFilter = null;
        if (is_string($filter) && !empty($filter)) {
            $nowFilter = explode(',', $filter);
        } else if ($filter !== false) {
            $defaultFilter = $this->config->services->filter->default_filter;
            $defaultFilter = isset($defaultFilter) ? explode(',', $defaultFilter) : [ ];
            if (is_array($filter)) {
                $defaultFilter = array_unique(array_merge($filter, $defaultFilter));
            }
            if (!empty($defaultFilter)) {
                $nowFilter = $defaultFilter;
            }
        }
        if (isset($name) && $name !== '') {
            if (isset($data[$name]) && $data[$name] !== '') {
                $data = $data[$name];
            } else {
                $data = $defaultValue;
            }
        }
        if (isset($nowFilter)) {
            $data = $this->filter->sanitize($data, $nowFilter, $noRecursive);
        }
        return $data;
    }
    
    /** 
     * @desc 转发到其他动作 
     * @param array|string $url  'App\Home\Controllers\forward/index/a/aaa?b=bbb' or 'forward/index/a/aaa?b=bbb' or 'index?b=bbb'
     * @param array|string $vars 参数 ['a'=>'aaa','b'=>'bbb'] or 'a=aaa&b=bbb'
     * @param sring $namespace 命名空间
     * @return void 
     * @author dengjing save
     * @date 2020年11月9日 15:11:26
     */
    final protected function forward($url, $vars = null, $namespace = null) {
        if (is_array($url)) {
            $forward = $url;
        } else if (is_string($url)) {
            $forward = [ ];
            $lastbBackslash = strrpos($url, '\\');
            if ($lastbBackslash) {
                $namespace = substr($url, 0, $lastbBackslash);
            }
            if (!empty($namespace)) {
                $forward['namespace'] = $namespace;
            }
            $start = $lastbBackslash === false ? 0 : $lastbBackslash + 1;
            $rest = substr($url, $start);
            $restStrposRes = strpos($rest, '?');
            if($rest == '' || $restStrposRes === 0){
                throw new Exception('方法不能为空');
            }
            if($restStrposRes === false){
                $capname = $rest;
                $paramsString = null;
            }else {
                list ($capname, $paramsString) = explode('?', $rest, 2);
                $capname = trim($capname, '/');
                if (empty($capname)) {
                    throw new Exception('控制器或方法不能为空');
                }
            }
            $capnameArr = explode('/', $capname);
            $capnameArrCount = count($capnameArr);
            if ($capnameArrCount == 1) {
                $forward['action'] = $capnameArr[0];
            } else {
                $forward['controller'] = $capnameArr[0];
                $forward['action'] = $capnameArr[1];
                for ($i = 2; $i < $capnameArrCount; $i += 2) {
                    $forward['params'][$capnameArr[$i]] = $capnameArr[$i + 1] ? $capnameArr[$i + 1] : null;
                }
            }
            if ($paramsString !== null) {
                parse_str($paramsString, $paramsArr);
                $forward['params'] = array_merge($forward['params'] ?? [ ], $paramsArr);
            }
        } else {
            throw new Exception('url只能为字符串或者数组');
        }
        if (is_string($vars)) {
            $vars = trim($vars, '?');
            parse_str($vars, $vars);
        }
        if (is_array($vars)) {
            $forward['params'] = array_merge($forward['params'] ?? [ ], $vars);
        }
        $this->dispatcher->forward($forward);
    }

    /**
     * @desc 获取get参数
     * @param string $name 参数名
     * @param string|array $filter 过滤类型，支持string、trim、absint、int、email、float、int!、float!、alphanum、striptags、lower、upper、url、special_chars
     * 当为false时，不使用默认过滤，当为字符串例如'string,trim'时采用参数过滤 ，当为数组例如['string','trim']时采用参数+默认过滤，当为null等其他值时时采用默认过滤
     * @param mixed $defaultValue 默认值
     * @param bool $noRecursive 不递归过滤
     * @return mixed
     * @author zhaoyang
     * @date 2018年5月8日 下午10:38:50
     */
    final protected function get(string $name = null, $filter = null, $defaultValue = null, $noRecursive = false) {
        $data = array_merge($this->request->getQuery(), $this->dispatcher->getParams());
        unset($data['_url']);
        return $this->sanitize($data, $name, $filter, $defaultValue, $noRecursive);
    }

    /**
     * @desc 获取post参数
     * @param string $name 参数名
     * @param string|array $filter 过滤类型，支持string、trim、absint、int、email、float、int!、float!、alphanum、striptags、lower、upper、url、special_chars
     * 当为false时，不使用默认过滤，当为字符串'string,trim'时采用参数过滤 ，当为数组['string','trim']时采用参数+默认过滤，当为null等其他值时时采用默认过滤
     * @param mixed $defaultValue 默认值
     * @param bool $noRecursive 不递归过滤
     * @param bool $notAllowEmpty 不允许为空
     * @return mixed
     * @author zhaoyang
     * @date 2018年5月9日 下午8:40:27
     */
    final protected function post(string $name = null, $filter = null, $defaultValue = null, $noRecursive = false, $notAllowEmpty = false) {
        $data = $this->request->getPost();
        return $this->sanitize($data, $name, $filter, $defaultValue, $noRecursive);
    }

    /**
     * @desc 获取post或者get参数
     * @param string $name 参数名
     * @param string|array $filter 过滤类型，支持string、trim、absint、int、email、float、int!、float!、alphanum、striptags、lower、upper、url、special_chars
     * 当为false时，不使用默认过滤，当为字符串例如'string,trim'时采用参数过滤 ，当为数组例如['string','trim']时采用参数+默认过滤，当为null等其他值时时采用默认过滤
     * @param mixed $defaultValue 默认值
     * @param bool $noRecursive 不递归过滤
     * @return mixed
     * @author zhaoyang
     * @date 2018年5月9日 下午9:41:49
     */
    final protected function request($name = null, $filter = null, $defaultValue = null, $noRecursive = false){
        if (isset($name) && $name !== '') {
            $params = $this->post($name, $filter, $defaultValue, $noRecursive) ?? $this->get($name, $filter, $defaultValue, $noRecursive);
            if (empty($params)){
               $params = $this->get_header($name);
            }
            return $params;
        }
        $params = array_merge($this->post(null, $filter, $defaultValue, $noRecursive), $this->get(null, $filter, $defaultValue, $noRecursive));
        if (empty($params)){
            $params = $this->get_header($name);
        } else {
            $header = $this->get_header();
            $params = array_merge($params,$header);
        }
        return $params;
    }

    final protected function get_header(){
        $headers = [];
        foreach ($_SERVER as $name => $value) {
            if (substr($name, 0, 5) == 'HTTP_') {
                $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
            }
        }
        return $headers;
    }
    /**
     * @param string $name 参数名
     * @param string|array $filter 过滤类型，支持string、trim、absint、int、email、float、int!、float!、alphanum、striptags、lower、upper、url、special_chars
     * 当为false时，不使用默认过滤，当为字符串例如'string,trim'时采用参数过滤 ，当为数组例如['string','trim']时采用参数+默认过滤，当为null等其他值时时采用默认过滤
     * @param mixed $defaultValue 默认值
     * @param bool $noRecursive 不递归过滤
     * @return mixed
     * @author zhaoyang
     * @date 2018年5月9日 下午10:43:11
     */
    final protected function json($name = null, $filter = null, $defaultValue = null, $noRecursive = false){
        $data = $this->request->getJsonRawBody(true);
        if (!is_array($data)) {
            return [ ];
        }
        return $this->sanitize($data, $name, $filter, $defaultValue, $noRecursive);
    }
    /**
     * sql验证
     * @return bool
     */
    public static function sql_check()
    {
        $getfilter = "'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
        $postfilter = "\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
        $cookiefilter = "\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
        foreach ($_GET as $key => $value) {
            if (self::stopattack($key, $value, $getfilter))
                return false;
        }
        foreach ($_POST as $key => $value) {
            if (self::stopattack($key, $value, $postfilter))
                return false;
        }
        foreach ($_COOKIE as $key => $value) {
            if (self::stopattack($key, $value, $cookiefilter))
                return false;
        }
        return true;
    }

    /**
     * 记录sql，验证
     * @param $StrFiltKey
     * @param $StrFiltValue
     * @param $ArrFiltReq
     * @return bool
     */
    public static function stopattack($StrFiltKey, $StrFiltValue, $ArrFiltReq)
    {
        if (is_array($StrFiltValue)) $StrFiltValue = implode($StrFiltValue);
        if (preg_match("/" . $ArrFiltReq . "/is", $StrFiltValue) == 1) {
            common::writes_log($_SERVER["REMOTE_ADDR"] . "    " . strftime("%Y-%m-%d %H:%M:%S") . "    " . $_SERVER["PHP_SELF"] . "    " . $_SERVER["REQUEST_METHOD"] . "    " . $StrFiltKey . "    " . $StrFiltValue);
            return false;
        }
        return true;
    }



    public function ok($data = null, $code = 1, $msg = '操作成功', $total = 0, $next_page = null)
    {
        header('Content-Type:application/json');
        $return_data['code'] = $code;
        $return_data['data'] = $data;
        $return_data['msg'] = $msg;
        echo json_encode($return_data, 1);
        exit();
    }

    public function fail($code = 0, $msg="",$data='')
    {
        header('Content-Type:application/json');
        $return_data['code'] = $code;
        $return_data['msg'] = $msg;
        $return_data['data'] = $data ? $data : [];
        echo json_encode($return_data, 1);
        exit();
    }
}